#include "world_base.h"
#include "../utils/sc_car_def_manager.h"
#include "../utils/sc_car_def_loader.h"
#include "src/filesystem/be_filesystem.h"

BaseWorld::BaseWorld() :
m_camera(SIMD_HALF_PI/2, 1024.0f/768.0f, 0.05f, 5000),
m_cameraFollow(SIMD_HALF_PI/2, 1024.0f/768.0f, 0.05f, 5000)
{
	settings = Settings::Instance();

	// setting shortcuts
	server = settings->getCVarPtr("server");
	headless = settings->getCVarPtr("headless");
	drawscene = settings->getCVarPtr("drawscene");
	follow = settings->getCVarPtr("follow");
	camera_follow = settings->getCVarPtr("camera_follow");
	joystickenabled = settings->getCVarPtr("joystick");

	if ( !*headless )
	{
		m_graphics.reset(new ScGraphics);
		joystick.reset(new Joystick);
	}

	// BULLET SETUP
	m_dynamicsWorld = m_physicsSystem.createWorld();

	// SET CAMERA POSITION
	m_sceneNodeCamera.setOrigin( btVector3( 600, 70, 0 ) );

	m_camera.setSceneNode(&m_sceneNodeCamera);
	m_cameraFollow.setSceneNode(&m_sceneNodeCameraFollow);

	ScCarDefLoader carDefLoader;
	BeFile befileCar;
	if ( BeFilesystem::Instance()->load(befileCar, "cars/miura_SV2/car.xml") )
	{
		carDefLoader.load( ScCarDefManager::instance(), &befileCar );
	}
}

void BaseWorld::newMessage(const string& msg)
{
	// input from scene, needs mutexing
	servermessages.push_back(msg);
}

void BaseWorld::newMessageAllClients(const string& msg)
{
	for ( unsigned int i=0; i < players.size(); i++ )
	{
		if ( players[i]->isApproved() )
		{
			players[i]->pushOutgoingmessage(msg);
		}
	}
}

void BaseWorld::newLogMessage(const string& msg)
{
	logbufferQueue.push_back(msg);
}

int BaseWorld::findClient(unsigned int id)
{
	for ( unsigned int k=0; k < players.size(); k++ )
		if ( players[k]->getId() == id )
			return k;
	return -1;
}

void BaseWorld::draw()
{
// 	exit(0);
// 	cerr << "setting up gl" << endl;

	const float timeDelta=Timer::Instance()->elapsed / 1000.0f;

// 	if ( map->m_skyBoxModel != 0 )

	if ( m_map )
	{
		if ( m_map->getSkyboxmodel() )
		{
			m_map->m_skyBoxAngle += 1.0f*timeDelta;
		}
	}

	btTransform offset2;
	offset2.setIdentity();

	btTransform offset;
	offset.setIdentity();
	
	// copy positions of entities
// 		for( unsigned int i=0; i < entities.size(); i++)
// 			entities[i]->copyPosition();

		for( unsigned int i=0; i < players.size(); i++)
			if ( players[i]->isJoined() )
			{
// 				players[i]->getCar()->copyPosition();
				if ( players[i] == me )
				{
					offset2.setFromOpenGLMatrix( me->getCar()->body.m_bodyparts[0]->drawposition );
					if( *follow && !*camera_follow )
					{
						players[i]->getCar()->m_drawChassis=false;
						offset.setOrigin(btVector3( 0, 0, 1 ));
					}
					else
					{
						players[i]->getCar()->m_drawChassis=true;
						offset.setOrigin(btVector3( 0, 1.25f, 6.5f ));
					}
				}
			}


	glViewport(0,0,*settings->winWidth,*settings->winHeight);

	btTransform skyBoxTransform;
	skyBoxTransform.setIdentity();

	if ( !*follow )
	{
		m_graphicsSystem.applyCamera(m_camera);
		skyBoxTransform=m_camera.getSceneNode()->getTransform();
	}
	else
	{
		if ( me->isJoined() )
		{
			BeSceneNode* const sceneNode=m_cameraFollow.getSceneNode();
			if(sceneNode)
			{
// 				if ( *camera_follow == 1 )
				sceneNode->setTransform(offset2*offset);
			}
			m_graphicsSystem.applyCamera(m_cameraFollow);
			skyBoxTransform=m_cameraFollow.getSceneNode()->getTransform();
		}
	}

	if ( *drawscene )
	{

		if( m_map !=0 && m_map->getSkyboxmodel() !=0 )
		{
			//m_graphicsSystem.disable(GL_CULL_FACE);
			m_graphicsSystem.matrixPush(GL_MODELVIEW);
			m_graphicsSystem.matrixTranslate(GL_MODELVIEW, skyBoxTransform.getOrigin().getX(), skyBoxTransform.getOrigin().getY(), skyBoxTransform.getOrigin().getZ());
			m_graphicsSystem.matrixRotate(GL_MODELVIEW, m_map->m_skyBoxAngle, 0, 1, 0);
			m_map->getSkyboxmodel()->draw();
			m_graphicsSystem.matrixPop(GL_MODELVIEW);
			//m_graphicsSystem.enable(GL_CULL_FACE);
		}

		m_graphicsSystem.enable(GL_LIGHTING);
		m_graphicsSystem.useProgram(&m_graphics->m_program);
		for( unsigned int i=0; i < entities.size(); i++)
			entities[i]->draw();

		for( unsigned int i=0; i < players.size(); i++)
			if ( players[i]->isJoined() )
				players[i]->getCar()->draw();
		m_graphicsSystem.useProgram(0);
		m_graphicsSystem.disable(GL_LIGHTING);
	}

	// add queue to logbuffer, preparing 2D
	for ( unsigned int i=0; i < logbufferQueue.size(); i++ )
	{
		Logbuffer::Instance()->add(logbufferQueue[i]);
	}
	logbufferQueue.clear();
	
}

BaseWorld::~BaseWorld()
{
	cerr << "exiting baseworld" << endl;
}
